iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 15
1
自我挑戰組

Kotlin Everyday:新手寫程式踩的坑系列 第 15

Day 15 ─用 Kotlin Fragment 做底部導覽欄 (2)

  • 分享至 

  • xImage
  •  

昨天設好導覽列,要讓點擊導覽列按鈕會跳去不同的頁面,這個功能看起來和 Activity 切換相似,卻是使用好幾個 Fragment 在同一個 Activity 裡面,用這個簡單例子練習 Fragment 的 Layout 和 Button 點擊事件怎麼載入。

Fragment
依附在 Activity 上的類別,一個 Activity 可以存在多個 Fragment,一個 Fragment 也可以被多個 Activity 複用。而作為切換頁面或分割畫面的工具, Fragment 也有自己的生命周期:

參考 Fragment 生命週期與載入

設定 Fragment

  1. 把 activity_main 想像是 layout 容器,除了 NavigationButton 之外不放任何東西,呈現空白,所有頁面將採用動態載入(這裡不講解靜態載入方式)
  2. 開始建立 Fragment:在app/java按右鍵新增三個空白的Fragment,會導入 .kt 檔及其對應的 xml 檔

    這時候可以看到 .kt 檔裡面已經自動建立好繼承 Fragment() 的 class,對應的畫面也透過 onCreateView 實例化,載入xml 畫面作為 Fragment的 View
//系統自動建立的class
class BlankFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_blank, container, false)
    }
}
  1. NavigationButton 有多個按鈕,要分別跳轉到不同 Fragment,我暫時將這三個 Fragment 的頁面設計用一個 TextView 標示

新的問題:
Fragment做好後,如何在 MainActivity 動態載入 Fragment?

首先要了解 Fragment 的載入方式,有分成靜態載入和動態載入兩種,靜態載入是在 layout.xml 中直接插入<Fragment>,意味著在 Activity 建立之初就直接建立呼叫 Fragment:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/LinearLayout1"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  tools:context=".MainActivity" >

  <fragment
      android:id="@+id/frag"
      class = "com.example.fish.day8_bottomnavigationfragmentintent.Fragment_0"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />
</LinearLayout>

動態載入則彈性很多,我們可以選擇在需要 Fragment 運作時才執行載入動作,基本動態載入會使用到 FragmentManagerFragmentTransaction

FragmentManager
用來管理 Fragment,處理其狀態及對它的生命週期進行監聽,可透過 getSupportFragmentManager() 方法來取得

val manager = supportFragmentManager

FragmentManager 有許多基本方法可以使用,比較常使用到的方法有 beginTransaction()、findFragmentById (id: Int)、findFragmentByTag (tag: String)等方法,這邊只會使用到第一種:

FragmentTransaction()
有了它之後可以對 Fragment做許多操作,例如載入 add、刪除 remove、顯示 show、隱藏 hide 等等,FragmentTransaction 可以透過 beginTransaction() 方法取得

val transaction = supportFragmentManager.beginTransaction()

稍微了解基本用法之後,就可以來把剛剛做的 Fragment 用進來,需要做的事情有以下幾種:

  • activity_main沒有畫面,所以要挑一個 Fragment 作為預設 layout
  • 修改 NavigationButton 按紐監聽的事件
  • 把 listener指給 NavigationButton

複習昨天 MainActivity 進度 ,只放到 NavigationButton的方法和做到一半的監聽器(如下)

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
     
    navigation.setOnNavigationItemSelectedListener ()
}

private var listener = object :BottomNavigationView.OnNavigationItemSelectedListener {
    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.item_fragment1 -> {
            }
            R.id.item_fragment2 -> {
            }
            R.id.item_fragment3 -> {
            }
        }
    }
}
  1. 把 fragment1 設為預設畫面,取得 FragmentManager 並使用 beginTransaction 的「replace」方法:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val manager = supportFragmentManager
    val transaction = manager.beginTransaction()
    transaction.replace(R.id.frameLayout, BlankFragment()).commit()
    
    navigation.setOnNavigationItemSelectedListener ()
}

FragmentTransaction 的方法有很多種,可以看小魚的Android Kotlin 實作 Day 8 來認識這幾種方法,add、remove、replace等等,這邊運用到「replace」是替換掉 container 中的 Fragment

FragmentTransaction replace (containerViewId: Int, fragment: Fragment, tag: String)
  • containerViewId:用來替換 Fragment 的 container
  • fragment:想載入的新的 Fragment
  • tag:為新載入 Fragment 設置 tag,可不需要此參數
  1. NavigationButton 按鈕對應要顯示的 Fragment
R.id.item_fragment2 -> {
    val manager = supportFragmentManager
    val transaction = manager.beginTransaction()
    transaction.replace(R.id.frameLayout, BlankFragment2()).commit()
    return true
}
  1. listener修改完,最後指給 setOnNavigationItemSelectedListener()
navigation.setOnNavigationItemSelectedListener (listener)

Fragment的點擊事件設定

做完之後才想到如果想為 Fragment 內的物件設置監聽事件,該怎麼做?
其實滿簡單的,只需要在 onCreateView() 實例化時操作、載入 View 的時候順便設置,例如想要在 Fragment2 放一個簡單的按紐,點擊之後會有 AlertDialog 對話方塊跳出來:

view.button_id.setOnClickListener{}   //實例化view之後取得點擊方法
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    
    val view = inflater.inflate(R.layout.fragment_blank_fragment2, container, false)
    view.btn_mail.setOnClickListener{
        AlertDialog.Builder(this.context)
            .setTitle("聯繫方式")
            .setMessage("我的信箱:zoeaeen13@gmail.com ")
            .setPositiveButton("確認"){dialog, _ ->
               dialog.dismiss()
            }
            .show()
    }
    return view  //回傳view
}


上一篇
Day 14 ─用 Kotlin Fragment 做底部導覽欄 BottomNavigation (1)
下一篇
Day 16 ─用 Kotlin 做待辦清單 Todolist(1) 使用Menu+RecycleView
系列文
Kotlin Everyday:新手寫程式踩的坑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言